#include "stdafx.h"
#include "EXListCtrlWnd.h"

// CEXListCtrlWnd

IMPLEMENT_DYNAMIC(CEXListCtrlWnd, CWnd)

CEXListCtrlWnd::CEXListCtrlWnd()
{
	m_nHScrollHeight = m_nVScrollWidth = m_nScrollW = m_nScrollH = GetSystemMetrics(SM_CYHSCROLL);
	m_dwListStyle = WS_CHILD|WS_VISIBLE|WS_CLIPCHILDREN;
	m_dwListExStyle = WS_EX_CLIENTEDGE;
	m_uExtraBitmapID = 0;
}

CEXListCtrlWnd::~CEXListCtrlWnd()
{

}


BEGIN_MESSAGE_MAP(CEXListCtrlWnd, CWnd)
	ON_WM_CREATE()
	ON_WM_SIZE()
	ON_WM_VSCROLL()
	ON_WM_HSCROLL()
	ON_WM_PAINT()
	ON_WM_ERASEBKGND()
	ON_WM_MOUSEWHEEL()
	ON_MESSAGE(UM_LIST_ERASE,			&CEXListCtrlWnd::OnDefListEraseNotify)
	ON_MESSAGE(UM_CUSTOMIZE_HEADER,     &CEXListCtrlWnd::OnCustomsizeHeader)
END_MESSAGE_MAP()



// CEXListCtrlWnd message handlers

LRESULT CEXListCtrlWnd::OnCustomsizeHeader(WPARAM, LPARAM lp)
{
	if (GetParent())
		GetParent()->PostMessage(UM_CUSTOMIZE_HEADER, 0, lp);

	return 0;
}

void CEXListCtrlWnd::SetResSet(CEXBaseResSet* pResSet)
{
  m_pListWndResSet = (CEXListCtrlWndResSet*)pResSet;

  m_ListCtrl.SetResSet(m_pListWndResSet->m_listCtrlResSet);
  m_VScroll.SetResSet(m_pListWndResSet->m_VscrollResSet);
  m_HScroll.SetResSet(m_pListWndResSet->m_HscrollResSet);
}

BOOL CEXListCtrlWnd::CreateCtrls()
{
	if (!IsWindow(GetSafeHwnd()))
		return FALSE;

	VERIFY(m_ListCtrl.Create(WS_CHILD|WS_VISIBLE|LVS_REPORT, 
                          CRect(0, 0, 0, 0), this, -1));
	VERIFY(m_VScroll.Create(SB_VERT|WS_CHILD|WS_VISIBLE, 
                          CRect(0, 0, 0, 0), this, -1));
	VERIFY(m_HScroll.Create(SB_HORZ|WS_CHILD|WS_VISIBLE, 
                          CRect(0, 0, 0, 0), this, -1));

	m_ListCtrl.SetScrolls(&m_VScroll, &m_HScroll);
	m_ListCtrl.SetExtendedStyle(m_ListCtrl.GetExStyle() | LVS_EX_DOUBLEBUFFER | 
              LVS_EX_HEADERDRAGDROP | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
	m_ListCtrl.SetBkColor(RGB(214, 228, 254));

	return TRUE;
}

int CEXListCtrlWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CWnd::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	CreateCtrls();

	return 0;
}

BOOL CEXListCtrlWnd::Create(const RECT& rect, CWnd* pParentWnd, UINT nID)
{
	DWORD dwStyle = WS_CHILD|WS_VISIBLE/*|WS_CLIPCHILDREN*/;
	if (m_dwListStyle & WS_BORDER)
		dwStyle |= WS_BORDER;

	DWORD dwExStyle = 0;
	if (m_dwListExStyle & WS_EX_CLIENTEDGE)
		dwExStyle |= WS_EX_CLIENTEDGE;

	if (m_dwListExStyle & WS_EX_WINDOWEDGE)
		dwExStyle |= WS_EX_WINDOWEDGE;

	if (m_dwListExStyle & WS_EX_STATICEDGE)
		dwExStyle |= WS_EX_STATICEDGE;

	return CWnd::CreateEx(dwExStyle, NULL, NULL, dwStyle, rect, pParentWnd, nID);
}

void CEXListCtrlWnd::OnSize(UINT nType, int cx, int cy)
{
	CWnd::OnSize(nType, cx, cy);

	if (IsWindow(GetSafeHwnd()))
	{
		SetLayout(cx, cy);
	}
}

void CEXListCtrlWnd::SetScrollWidth(UINT nScrollWidth)
{
	m_nHScrollHeight = m_nVScrollWidth = m_nScrollW = m_nScrollH = nScrollWidth;

	CRect rcClient;
	GetClientRect(rcClient);
	SetLayout(rcClient.Width(), rcClient.Height());
}

void CEXListCtrlWnd::SetHScrollHeight(UINT nScrollHeight)
{
	m_nHScrollHeight = m_nScrollH = nScrollHeight;
}

void CEXListCtrlWnd::SetVScrollWidth(UINT nScrollWidth)
{
	m_nVScrollWidth = m_nScrollW = nScrollWidth;
}

void CEXListCtrlWnd::SetLayout(int nWidth, int nHeight)
{
	if (IsWindow(m_VScroll.GetSafeHwnd()))
	{
		if (m_ListCtrl.GetItemCount())
		{
			CRect rcVScroll;
			rcVScroll.left = nWidth - m_nVScrollWidth;
			rcVScroll.right = nWidth;
			rcVScroll.top = 0;
			rcVScroll.bottom = nHeight - m_nHScrollHeight;
			m_VScroll.SetWindowPos(NULL, rcVScroll.left, rcVScroll.top, 
                            rcVScroll.Width(), rcVScroll.Height(), 
                            SWP_NOZORDER|SWP_FRAMECHANGED);
		}
	}

	if (IsWindow(m_HScroll.GetSafeHwnd()))
	{
		{
			CRect rcHScroll;
			rcHScroll.left = 0;
			rcHScroll.right = nWidth - m_nVScrollWidth;
			rcHScroll.top = nHeight - m_nHScrollHeight;
			rcHScroll.bottom = nHeight;
			m_HScroll.SetWindowPos(NULL, rcHScroll.left, rcHScroll.top, 
                            rcHScroll.Width(), rcHScroll.Height(), 
                            SWP_NOZORDER|SWP_FRAMECHANGED);
		}
	}

	if (IsWindow(m_ListCtrl.GetSafeHwnd()))
	{
		CRect rcList;
		rcList.left = 0;
		rcList.right = nWidth - m_nVScrollWidth;
		rcList.top = 0;
		rcList.bottom = nHeight - m_nHScrollHeight;
		m_ListCtrl.MoveWindow(rcList);
	}
}

void CEXListCtrlWnd::HScrollShow(BOOL bShow)
{
	m_nHScrollHeight = bShow ? m_nScrollH : 0;

	CRect rcClient;
	GetClientRect(rcClient);
	SetLayout(rcClient.Width(), rcClient.Height());
}

void CEXListCtrlWnd::VScrollShow(BOOL bShow)
{
	m_nVScrollWidth = bShow ? m_nScrollW : 0;

	CRect rcClient;
	GetClientRect(rcClient);
	SetLayout(rcClient.Width(), rcClient.Height());	
}

void CEXListCtrlWnd::SetListCtrl(CListCtrl * pList, COLORREF crBkgnd)
{
	m_dwListStyle = pList->GetStyle();
	m_dwListExStyle = pList->GetExStyle();

 	if (!IsWindow(GetSafeHwnd()))
 		VERIFY(Create(CRect(0,0,0,0), pList->GetParent(), -1));

	pList->SetParent(this);

	if (IsWindow(m_ListCtrl.GetSafeHwnd()))
		m_ListCtrl.DestroyWindow();

	VERIFY(m_ListCtrl.SubclassWindow(pList->GetSafeHwnd()));
	m_ListCtrl.ModifyStyleEx(WS_EX_STATICEDGE|WS_EX_CLIENTEDGE, 0);
	m_ListCtrl.SetExtendedStyle(m_ListCtrl.GetExtendedStyle() | 
                              LVS_EX_DOUBLEBUFFER | LVS_EX_HEADERDRAGDROP | 
                              LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);

	m_ListCtrl.SetBkColor(crBkgnd);
	m_ListCtrl.SetScrolls(&m_VScroll, &m_HScroll);
	
	CRect rcWnd;
	m_ListCtrl.GetWindowRect(rcWnd);

	GetParent()->ScreenToClient(rcWnd);

	MoveWindow(rcWnd);
}

int CEXListCtrlWnd::InsertColumn(int nCol, const LVCOLUMN* pColumn)
{
	return m_ListCtrl.InsertColumn(nCol, pColumn);
}

int CEXListCtrlWnd::InsertColumn(int nCol, LPCTSTR lpszColumnHeading, 
                                 int nFormat /*= LVCFMT_LEFT*/, 
                                 int nWidth /*= -1*/, int nSubItem /*= -1*/)
{
	return m_ListCtrl.InsertColumn(nCol, lpszColumnHeading, nFormat, 
                                nWidth, nSubItem);
}

int CEXListCtrlWnd::InsertItem(const LVITEM* pItem)
{
	return m_ListCtrl.InsertItem(pItem);
}

int CEXListCtrlWnd::InsertItem(int nItem, LPCTSTR lpszItem)
{
	return m_ListCtrl.InsertItem(nItem, lpszItem);
}

int CEXListCtrlWnd::InsertItem(int nItem, LPCTSTR lpszItem, int nImage)
{
	return m_ListCtrl.InsertItem(nImage, lpszItem, nImage);
}


void CEXListCtrlWnd::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	SCROLLINFO siv = {0};
	siv.cbSize = sizeof(SCROLLINFO);
	siv.fMask = SIF_ALL;
	m_ListCtrl.GetScrollInfo(SB_VERT, &siv);
	siv.nPage = m_ListCtrl.GetCountPerPage();
	m_ListCtrl.SetScrollInfo(SB_VERT, &siv);

	m_ListCtrl.SendMessage(WM_VSCROLL,MAKELONG(nSBCode,nPos),0);

	m_VScroll.SetScrollPos(m_ListCtrl.GetScrollPos(SB_VERT));

	m_ListCtrl.RedrawWindow(NULL, NULL, RDW_NOERASE|RDW_INVALIDATE|RDW_UPDATENOW);

	CWnd::OnVScroll(nSBCode, nPos, pScrollBar);
}

void CEXListCtrlWnd::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	CRect rcList;
	m_ListCtrl.GetClientRect(&rcList);

	SCROLLINFO sih = {0};
	sih.cbSize = sizeof(SCROLLINFO);
	sih.fMask = SIF_ALL;
	m_ListCtrl.GetScrollInfo(SB_HORZ, &sih);
	sih.nPage = rcList.Width();
	m_ListCtrl.SetScrollInfo(SB_HORZ, &sih);

	m_ListCtrl.SendMessage(WM_HSCROLL,MAKELONG(nSBCode,nPos),0);

	m_HScroll.SetScrollPos(m_ListCtrl.GetScrollPos(SB_HORZ));

	m_ListCtrl.RedrawWindow(NULL, NULL, RDW_NOERASE|RDW_INVALIDATE|RDW_UPDATENOW);

	CWnd::OnHScroll(nSBCode, nPos, pScrollBar);
}

void CEXListCtrlWnd::OnPaint()
{
	CPaintDC dc(this); 

	CRect rcExtra;
	GetClientRect(rcExtra);
	rcExtra.left = rcExtra.right - m_nVScrollWidth;
	rcExtra.top = rcExtra.bottom - m_nHScrollHeight;

	if (m_uExtraBitmapID)
	{
		BITMAP bmInfo = {0};
		m_bmpExtra.GetBitmap(&bmInfo);

		CDC dcExtra;
		dcExtra.CreateCompatibleDC(&dc);

		CBitmap * pOldBitmap = NULL;
		pOldBitmap = dcExtra.SelectObject(&m_bmpExtra);

		dc.StretchBlt(rcExtra.left, rcExtra.top, rcExtra.Width(), rcExtra.Height(), 
                  &dcExtra, 0, 0, bmInfo.bmWidth, bmInfo.bmHeight, SRCCOPY);

		dcExtra.SelectObject(pOldBitmap);
	}
	else
		dc.FillSolidRect(&rcExtra, GetSysColor(COLOR_3DFACE));
}

BOOL CEXListCtrlWnd::OnEraseBkgnd(CDC* pDC)
{
	UNREFERENCED_PARAMETER(pDC);
	return FALSE;
}

BOOL CEXListCtrlWnd::SetItemText(int nItem, int nSubItem, LPCTSTR lpszText)
{
	return m_ListCtrl.SetItemText(nItem, nSubItem, lpszText);
}

BOOL CEXListCtrlWnd::PreTranslateMessage(MSG* pMsg)
{
	if (pMsg->message == WM_MOUSEWHEEL)
	{
		pMsg->hwnd = GetSafeHwnd();
	}

	return CWnd::PreTranslateMessage(pMsg);
}


BOOL CEXListCtrlWnd::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
	int nCurPos = m_ListCtrl.GetScrollPos(SBS_VERT);

	int nCount = zDelta / 120;

	WORD nDirection = SB_LINEUP;
	WORD nPos = nCurPos;

	if (nCount < 0)
	{
		nDirection = SB_LINEDOWN;
		nCount = -nCount;
	}

	for (int i=0; i<nCount; i++)
	{
		m_VScroll.PostMessage(WM_DEF_MOUSEWHEEL, WPARAM(nDirection), NULL);
	}

	return CWnd::OnMouseWheel(nFlags, zDelta, pt);
}

void CEXListCtrlWnd::SetHScrollLeftArrow(UINT nID, int nPic)
{
	m_HScroll.SetLeftUpButtonBitmap(nID, nPic);
}

void CEXListCtrlWnd::SetHScrollRightArrow(UINT nID, int nPic)
{
	m_HScroll.SetRightDownButtonBitmap(nID, nPic);
}

void CEXListCtrlWnd::SetHScrollPage(UINT nID, int nPic)
{
	m_HScroll.SetPageButtonBitmap(nID, nPic);
}

void CEXListCtrlWnd::SetHScrollThumb(UINT nID, UINT nBkgndID, UINT nIconID, 
                                     int nPic, int nLeftWidth /*= 0*/, 
                                     int nRightWidth /*= 0*/,
									                   int nTopHeight /*= 0*/, 
                                     int nBottomHeight /*= 0*/)
{
	m_HScroll.SetThumbBitmap(nID, nBkgndID, nIconID, nPic, nLeftWidth, 
                          nRightWidth, nTopHeight, nBottomHeight);
}

void CEXListCtrlWnd::SetVScrollLeftArrow(UINT nID, int nPic)
{
	m_VScroll.SetLeftUpButtonBitmap(nID, nPic);
}

void CEXListCtrlWnd::SetVScrollRightArrow(UINT nID, int nPic)
{
	m_VScroll.SetRightDownButtonBitmap(nID, nPic);
}

void CEXListCtrlWnd::SetVScrollPage(UINT nID, int nPic)
{
	m_VScroll.SetPageButtonBitmap(nID, nPic);
}

void CEXListCtrlWnd::SetVScrollThumb(UINT nID, UINT nBkgndID, UINT nIconID, 
                                     int nPic, int nLeftWidth /*= 0*/, 
                                     int nRightWidth /*= 0*/,
									                   int nTopHeight /*= 0*/, 
                                     int nBottomHeight /*= 0*/)
{
	m_VScroll.SetThumbBitmap(nID, nBkgndID, nIconID, nPic, nLeftWidth, 
                            nRightWidth, nTopHeight, nBottomHeight);
}

void CEXListCtrlWnd::SetExtra(UINT nID)
{
	m_uExtraBitmapID = nID;

	m_bmpExtra.DeleteObject();
	m_bmpExtra.LoadBitmap(m_uExtraBitmapID);

	Invalidate();
}

void CEXListCtrlWnd::SubClassHeaderCtrl()
{
	m_ListCtrl.SubclassHeaderCtrl();
}

void CEXListCtrlWnd::SetHeaderBitmap(UINT nID)
{
	m_ListCtrl.SetHeaderBitmap(nID);
}

void CEXListCtrlWnd::SetHeaderColor(COLORREF crHeader)
{
	m_ListCtrl.SetHeaderColor(crHeader);
}

void CEXListCtrlWnd::SetListCtrlName(CString strName)
{
	m_ListCtrl.SetListCtrlName(strName);
}

DWORD CEXListCtrlWnd::SetExtendedStyle(DWORD dwNewStyle)
{
	return m_ListCtrl.SetExtendedStyle(dwNewStyle);
}

DWORD CEXListCtrlWnd::GetExtendedStyle()
{
	return m_ListCtrl.GetExtendedStyle();
}

BOOL CEXListCtrlWnd::SetItemState(int nItem, LVITEM* pItem)
{
	return m_ListCtrl.SetItemState(nItem, pItem);
}

BOOL CEXListCtrlWnd::SetItemState(int nItem, UINT nState, UINT nMask)
{
	return m_ListCtrl.SetItemState(nItem, nState, nMask);
}

int CEXListCtrlWnd::GetItemCount() const
{
	return m_ListCtrl.GetItemCount();
}

DWORD_PTR CEXListCtrlWnd::GetItemData(int nItem) const
{
	return m_ListCtrl.GetItemData(nItem);
}

BOOL CEXListCtrlWnd::SetItemData(int nItem, DWORD_PTR dwData)
{
	return m_ListCtrl.SetItemData(nItem, dwData);
}

BOOL CEXListCtrlWnd::DeleteAllItems()
{
	return m_ListCtrl.DeleteAllItems();
}

BOOL CEXListCtrlWnd::DeleteItem(int nItem)
{
	return m_ListCtrl.DeleteItem(nItem);
}

POSITION CEXListCtrlWnd::GetFirstSelectedItemPosition() const
{
	return m_ListCtrl.GetFirstSelectedItemPosition();
}

int CEXListCtrlWnd::GetNextSelectedItem(POSITION& pos) const
{
	return m_ListCtrl.GetNextSelectedItem(pos);
}

UINT CEXListCtrlWnd::GetSelectedCount() const
{
	return m_ListCtrl.GetSelectedCount();
}

CListCtrl * CEXListCtrlWnd::operator & ()
{
	return &m_ListCtrl;
}

LRESULT CEXListCtrlWnd::OnDefListEraseNotify(WPARAM w, LPARAM l)
{
	m_ListCtrl.SetErase((BOOL)w);
	if ((BOOL)w)
		m_ListCtrl.RedrawWindow();

	return 0;
}

CString CEXListCtrlWnd::GetItemText(int nItem, int nSubItem) const
{
	return m_ListCtrl.GetItemText(nItem, nSubItem);
}

int CEXListCtrlWnd::GetItemText(__in int nItem, __in int nSubItem, 
                         __out_ecount_part_z(nLen, return + 1) LPTSTR lpszText, 
                         __in int nLen) const
{
	return m_ListCtrl.GetItemText(nItem, nSubItem, lpszText, nLen);
}

BOOL CEXListCtrlWnd::EnsureVisible(int nItem, BOOL bPartialOK)
{
	return m_ListCtrl.EnsureVisible(nItem, bPartialOK);
}

void CEXListCtrlWnd::Sort(int nColumn, BOOL bAscend)
{
//	m_ListCtrl.Sort(nColumn, bAscend);
}

void CEXListCtrlWnd::Sort()
{
	m_ListCtrl.Sort();
}

void CEXListCtrlWnd::SetListColor(COLORREF crEven, COLORREF crOdd)
{
	m_ListCtrl.SetListColor(crEven, crOdd);
}

void CEXListCtrlWnd::SetTextColor(COLORREF crText)
{
	m_ListCtrl.SetTextColor(crText);
}

void CEXListCtrlWnd::SetFont(CFont* pFont, BOOL bRedraw /*= TRUE*/)
{
	m_ListCtrl.SetFont(pFont, bRedraw);
}

void CEXListCtrlWnd::GetSortColumn(CString & strColumn, BOOL & bAscend)
{
	m_ListCtrl.GetSortColumn(strColumn, bAscend);
}

CEXListCtrlWnd * CEXListCtrlWnd::GetAddress()
{
	return this;
}

int CEXListCtrlWnd::GetColumnWidth(int nCol) const
{
	return m_ListCtrl.GetColumnWidth(nCol);
}

BOOL CEXListCtrlWnd::SetColumnWidth(int nCol, int cx)
{
	return m_ListCtrl.SetColumnWidth(nCol, cx);
}

int CEXListCtrlWnd::GetHotItem()
{
	return m_ListCtrl.GetHotItem();
}

int CEXListCtrlWnd::SetHotItem(int iIndex)
{
	return m_ListCtrl.SetHotItem(iIndex);
}

BOOL CEXListCtrlWnd::SelectItem(int nIndex, BOOL bSelect /*= TRUE*/)
{
	if (bSelect)
		return m_ListCtrl.SetItemState(nIndex, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED);
	else
		return m_ListCtrl.SetItemState(-1, 0, LVIS_SELECTED|LVIS_FOCUSED);
}

void CEXListCtrlWnd::SetItemCount(int nItems)
{
	m_ListCtrl.SetItemCount(nItems);
}

